#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <mutex>
#include <unordered_map>
#include <memory>
#include <functional>
#include <unistd.h>
#include <stdint.h>
#include <sys/timerfd.h>

using timeTask_t = std::function<void()>;
using Release_t = std::function<void()>;
// 任务类
struct TimerTask
{
    uint64_t _id;           // 任务对象的id--外部设置
    uint32_t _timeout;      // 超时时间--外部设置
    timeTask_t _task_cb;    // 析构时执行的回调方法--外部设置
    Release_t _release_cb;  // 从时间轮中移除TimeTask对象
    bool _iscancel = false; // 表示任务事都取消？--true == 是 false == 否
    TimerTask(uint64_t id, uint32_t timeout, const timeTask_t &task) : _id(id), _timeout(timeout), _task_cb(task)
    {
    }
    ~TimerTask()
    {
        // 析构时执行回调方法--断开超时链接
        if (!_iscancel)
            _task_cb();
        // 执行完从时间轮中移除
        _release_cb();
    }
    // 设置释放资源的回调方法
    void SetReleaseCb(const Release_t release)
    {
        _release_cb = release;
    }
    // 取消本任务
    void Cancel()
    {
        _iscancel = true;
    }
};
// 时间轮刻度等级
static const int SECOND_WHEEL = 60;
static const int MINUTE_WHEEL = 60;
static const int HOUR_WHEEL = 24;
// 时间轮定时器
using std::vector;
class TimeWheel
{
private:
    using TaskPtr = std::shared_ptr<TimerTask>;
    using WeakTaskPtr = std::weak_ptr<TimerTask>;

private:
    vector<vector<TaskPtr>> _wheels;                   // 时间轮
    int _tick;                                         // 指针--指向的时钟位置任务被执行
    int _capacity;                                     // 时间轮的最大延迟时间
    std::unordered_map<uint64_t, WeakTaskPtr> _timers; // 通过id找到weak_ptr管理的TimerTask对象--解决循环引用
public:
    TimeWheel(int pritick = 0,int timelevel = SECOND_WHEEL) : _tick(pritick), _capacity(timelevel), _wheels(timelevel)
    {
    }
    void RemoveTask(uint64_t id)
    {
        auto pos = _timers.find(id);
        if (pos != _timers.end())
        {
            _timers.erase(id);
        }
    }
    // 向时间轮添加任务对象
    void AddTask(uint64_t id, uint32_t timeout, const timeTask_t &task)
    {
        // 构建TimerTask对象
        TaskPtr newTaskTPtr(new TimerTask(id, timeout, task));
        newTaskTPtr->SetReleaseCb(std::bind(&TimeWheel::RemoveTask, this, id));
        // 添加进时间轮
        int pos = (_tick + timeout) % _capacity;
        _wheels[pos].push_back(newTaskTPtr);
        // 添加进查找表
        _timers[id] = WeakTaskPtr(newTaskTPtr);
    }
    // 延迟/刷新任务执行的时间
    void DelayTaskForTime(uint64_t id)
    {
        auto pos = _timers.find(id);
        if (pos == _timers.end())
        {
            return;
        }
        // 获取被weak_ptr管理的对象
        TaskPtr ptr = _timers[id].lock();
        // 计算新的时钟位置
        int newpos = (_tick + ptr->_timeout) % _capacity;
        // 重新添加
        _wheels[newpos].push_back(ptr);
    }
    // 外界调用该函数--1s/次
    void RunTimeTask()
    {
        _tick = (_tick + 1) % _capacity;
        // 析构该位置挂载的所有任务对象
        _wheels[_tick].clear();
    }
    void TimeTaskCancel(uint64_t id)
    {
        auto pos = _timers.find(id);
        if (pos == _timers.end())
        {
            return;
        }
        TaskPtr ptr = _timers[id].lock();
        if (ptr)
            ptr->Cancel();
    }
};